package controller;

import server.*;
import common.*;
import java.util.*;

/**
 */
public abstract class GameController extends Wrap {

    /** reference to the GameServer */
    protected GameServer gameServer;

    /**
     * GameServer will call this init method immediately after construction.
     * It is final so that this initialization does not got overridden by subclasses.
     * Initialization for subclasses is done in the initController() method below.
     */
    public final void init(GameServer s, GameConfig gc) {
	this.gameServer = s;

	// todo: get the preferred number of workers from the GameConfig
	//	int nw = gc.getInt("NUM_WORKERS", 5);

	// init the Wrap first
	initWrap(Globals.DEFAULT_CONTROLLER_WORKERS);
	// now call the subclasses' init
	initController(gc);
    }

    /**
     * utility method for sending events
     */
    protected void sendEvent(GameEvent e, Player p) {
	e.setPlayerId(p.getPlayerId());
	gameServer.writeEvent(e);
    }

    /** 
     * utilidad que envia el evento a todos los jugadores menos al activo 
     */
    protected synchronized void sendBroadcastEvent(GameEvent e, Collection players) {
	Iterator i = players.iterator();
	String[] recipients = new String[players.size()];
	int j=0;
	while(i.hasNext()) {
	    Player p = (Player) i.next();
	    if (!(p.getPlayerId().equals(e.getPlayerId()))) 
		recipients[j++] = p.getPlayerId();
	}
	e.setRecipients(recipients);
	gameServer.writeEvent(e);
    }

    /** 
     * utilidad que envia el evento a todos los jugadores
     */
    protected synchronized void sendBroadcastEventAll(GameEvent e, Collection players) {
	Iterator i = players.iterator();
	String[] recipients = new String[players.size()];
	int j=0;
	while(i.hasNext()) {
	    Player p = (Player) i.next();
		recipients[j++] = p.getPlayerId();
	}
	e.setRecipients(recipients);
	gameServer.writeEvent(e);
    }
    
    /**
     * Metodo en cargado de iniciar todas las consolas de juego
     * @param e
     * @param players
     */
    protected synchronized void startGameAll(Collection players, String turno,GameEvent fTurn) {
    	GameEvent  e = new GameEventDefault("S",fTurn.getType());
    	e.setNick(fTurn.getNick());
    	e.setImagenJugador(fTurn.getImagenJugador());
    	Iterator i = players.iterator();
    	String[] recipients = new String[players.size()-1];
    	int j=0;
    	while(i.hasNext())
    	{
    	    Player p = (Player) i.next();
    	    if (!p.getSessionId().equals(turno))
    	    	recipients[j++] = p.getPlayerId();
    	}
    	    	
    	e.setRecipients(recipients);
    	e.getBloqueado();
    	gameServer.writeEvent(e);
    }

    /**
     * envia el mensaje de no bloqueo al primer turno
     * @param players
     * @param turno
     * @param eventAnt
     */
    protected synchronized GameEvent launchFirstTurn(Collection players, String turno, int tipo) {
    //se le envia al primero bloqueado en N
    	GameEvent  e = new GameEventDefault("N",tipo);
    	
    	Iterator i = players.iterator();
    	i = players.iterator();
    	
    	String []recipientes = new String[1];
    	while(i.hasNext())
    	{
    	    Player p = (Player) i.next();
    	    if (p.getSessionId().equals(turno)){
    	    	recipientes[0]=p.getPlayerId();
    	    	e.setNick(p.getNick());
    	    	e.setImagenJugador(p.getImagen());
    	    	e.setPlayerId(p.getPlayerId());
    	    	e.setSessionId(p.getSessionId());
    	    }
    	    	
    	}
    	
    	e.setRecipients(recipientes);
    	
    	for (int p=0;p<e.getRecipients().length;p++)
    		gameServer.writeEvent(e);
    	return e;
    }
    
    
    /**
     * Metodo encargado de veirifcar que todos hallan dado empezar
     * @param e
     * @param players
     * @return
     */
    protected Player isStartGame (GameEvent e, Collection players)
    {
    	Player jugador=null;
    	Iterator i = players.iterator();
    	int j=0;
    	while(i.hasNext()) {
    	    Player p = (Player) i.next();
    	    if ((p.getPlayerId().equals(e.getPlayerId())))
    	    {
    	    	p.setInGame(true);
    	    	jugador=p;
    	    }
    	}
    	i = players.iterator();
    	while(i.hasNext()) {
    	    Player p = (Player) i.next();
    	    if(!p.inGame())
    	    	return jugador;
    	}
    	return null;
    }
    
    /** 
     * GameController subclasses should implement initController 
     * in order to do any initialization they require.
     */
    protected abstract void initController(GameConfig gc);

    /**
     * subclasses must implement to provide their GameName
     */
    public abstract String getGameName();
    
    /** 
     * factory method for fetching Player objects
     */
    public abstract Player createPlayer();

    /** 
     * factory method for fetching GameEvent objects
     */
    public abstract GameEvent createGameEvent();

}



